home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / ODUtils / Unused / PlfmFile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-16  |  47.8 KB  |  1,628 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        PlfmFile.cpp
  3.  
  4.     Contains:    Implmentation for PlatformFile class
  5.  
  6.     Owned by:    Vincent Lo
  7.  
  8.     Copyright:    © 1993-95 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #ifndef _ODTYPES_
  13. #include "ODTypes.h"
  14. #endif
  15.  
  16. #ifndef _PLFMFILE_
  17. #include "PlfmFile.h"
  18. #endif
  19.  
  20. #ifndef _ODMEMORY_
  21. #include "ODMemory.h"
  22. #endif
  23.  
  24. #ifndef _EXCEPT_
  25. #include "Except.h"
  26. #endif
  27.  
  28. #ifndef _ODDEBUG_
  29. #include "ODDebug.h"
  30. #endif
  31.  
  32. #ifndef _PASCLSTR_
  33. #include "PasclStr.h"
  34. #endif
  35.  
  36. #ifndef _ITEXT_
  37. #include "IText.h"
  38. #endif
  39.  
  40. #ifndef _DOCUTILS_
  41. #include "DocUtils.h"
  42. #endif
  43.  
  44. #ifndef _DLOGUTIL_
  45. #include <DlogUtil.h>
  46. #endif
  47.  
  48. #ifndef _UTILDEFS_
  49. #include "UtilDefs.h"
  50. #endif
  51.  
  52. #ifndef _TEMPOBJ_
  53. #include "TempObj.h"
  54. #endif
  55.  
  56. #ifndef _UTILERRS_
  57. #include "UtilErrs.h"
  58. #endif
  59.  
  60. #ifndef __FILES__
  61. #include <Files.h>
  62. #endif
  63.  
  64. #ifndef __FOLDERS__
  65. #include <Folders.h>
  66. #endif
  67.  
  68. #ifndef __FINDER__
  69. #include <Finder.h>
  70. #endif
  71.  
  72. #ifndef __ICONS__
  73. #include <Icons.h>
  74. #endif
  75.  
  76. #ifndef __STRING__
  77. #include <string.h>
  78. #endif
  79.  
  80. #ifndef __ERRORS__
  81. #include <Errors.h>
  82. #endif
  83.  
  84. #ifndef __TEXTUTILS__
  85. #include "TextUtils.h"
  86. #endif
  87.  
  88. #ifndef _USERSRCM_
  89. #include <UseRsrcM.h>
  90. #endif
  91.  
  92. #ifndef __TEXTUTILS__
  93. #include "TextUtils.h"
  94. #endif
  95.  
  96. #pragma segment PlatformFile
  97.  
  98. //==============================================================================
  99. // Constants
  100. //==============================================================================
  101.  
  102. const    ODSShort    kMaxFileNameSize        = 64;
  103.  
  104. #define    kFileContainerType                    'ctyp'
  105. #define    kFileContainerTypeResID                1
  106.  
  107. const ODULong    kMaxCopyBufferSize            = 32 * 1024L;
  108. const ODULong    kMinCopyBufferSize            = 512;
  109.  
  110. static const ResType            kIconType[6] = {'ICN#','icl4','icl8','ics#','ics4','ics8'};
  111. static const short                kIconSize[6] = {256,   512,   1024,  64,    128,   256   };
  112.  
  113. //==============================================================================
  114. // Scalar Types
  115. //==============================================================================
  116.  
  117. //==============================================================================
  118. // Local Classes
  119. //==============================================================================
  120.  
  121. //==============================================================================
  122. // Global Variables
  123. //==============================================================================
  124.  
  125. //==============================================================================
  126. // Function Prototype
  127. //==============================================================================
  128.  
  129. //==============================================================================
  130. // PlatformFile
  131. //==============================================================================
  132.  
  133. const ODOSType kBogusOSType = 0;    // Default type/creator value until it's read
  134.  
  135. //------------------------------------------------------------------------------
  136. // PlatformFile::PlatformFile
  137. //------------------------------------------------------------------------------
  138. PlatformFile::PlatformFile()
  139. {
  140.     fContainerType = kODNULL;
  141.     fCreator = kBogusOSType;
  142.     fFileType = kBogusOSType;
  143.     fScriptTag = smSystemScript;
  144.     
  145.     fFileSpec.vRefNum = 0;
  146.     fFileSpec.parID = 0;
  147.     fFileSpec.name[0] = 0;
  148.     fDataRefNum = 0;
  149.     fFileID = kODNoFileID;
  150.     fPermission = fsCurPerm;
  151.     fResRefNum = kODNoFileRefNum;
  152.     fResOpenStack = 0;
  153.     fNeedToClose = kODFalse;
  154.     
  155.     fVolModDate = fTimeLastChecked = 0;
  156. }
  157.  
  158. //------------------------------------------------------------------------------
  159. // PlatformFile::~PlatformFile
  160. //------------------------------------------------------------------------------
  161. PlatformFile::~PlatformFile()
  162. {
  163.     ODDisposePtr(fContainerType);
  164. }
  165.  
  166. //------------------------------------------------------------------------------
  167. // PlatformFile::Specify
  168. //------------------------------------------------------------------------------
  169. void PlatformFile::Specify(const ODFileSpec* fileSpec)
  170. {
  171.     fFileSpec = *fileSpec;
  172.     fCreator = kBogusOSType;
  173.     fFileType = kBogusOSType;
  174.     fFileID = kODNoFileID;
  175. }
  176.  
  177. void PlatformFile::SpecifyFromFile(PlatformFile* file)
  178. {
  179.     const ODFileSpec &fileSpec = file->GetFileSpec();
  180.     this->Specify(&fileSpec);
  181. }
  182.  
  183. //------------------------------------------------------------------------------
  184. // PlatformFile::SetAsciiname
  185. //------------------------------------------------------------------------------
  186. void PlatformFile::SetAsciiName(const char* asciiName)
  187. {
  188.     ODSByte pname[kMaxFileNameSize+1];
  189.     strncpy(pname,asciiName,kMaxFileNameSize);
  190.     pname[kMaxFileNameSize] = 0;
  191.     
  192.     CToPascalString(pname);
  193.     if (fFileSpec.vRefNum == 0 &&
  194.         fFileSpec.parID == 0 &&
  195.         fFileSpec.name[0] == 0)
  196.     {
  197.         FSMakeFSSpec(0, 0, (StringPtr)pname, &fFileSpec);
  198.     }
  199.     else
  200.     {
  201.         CopyPascalString(fFileSpec.name,(StringPtr)pname);
  202.     }    
  203.     this->Specify(&fFileSpec);
  204. }
  205.  
  206. //------------------------------------------------------------------------------
  207. // PlatformFile::IsLocked
  208. //------------------------------------------------------------------------------
  209. ODBoolean PlatformFile::IsLocked()
  210. {
  211.     CInfoPBRec    pbBlock;
  212.     ODBoolean    result = kODFalse;
  213.  
  214.     // Check to see whether the volume is locked
  215.  
  216.     // Eric's original code with slight modifications.
  217.     // Appears to be needed in the case of a locked floppy. -TÇ
  218.     HParamBlockRec pb;
  219.     pb.volumeParam.ioCompletion = kODNULL;
  220.     pb.volumeParam.ioNamePtr = kODNULL;
  221.     pb.volumeParam.ioVRefNum = fFileSpec.vRefNum;
  222.     pb.volumeParam.ioVolIndex = 0;
  223.  
  224.     THROW_IF_ERROR(PBHGetVInfoSync(&pb));
  225.  
  226.     // <eeh> I have no clue if this "0x80"is right!!!  Find out what
  227.     // the constant is for write-access possible....
  228.  
  229.     result = (pb.volumeParam.ioVAtrb & 0x80) ? kODTrue : kODFalse;
  230.  
  231.     // Check to see whether the directory is locked
  232.     if (result == kODFalse) {
  233.         // first assume it is a file share volume
  234.         HParamBlockRec    paramBlk;
  235.         paramBlk.accessParam.ioCompletion = kODNULL;
  236.         paramBlk.accessParam.ioNamePtr = kODNULL;
  237.         paramBlk.accessParam.ioVRefNum = fFileSpec.vRefNum;
  238.         paramBlk.accessParam.ioDirID = fFileSpec.parID;
  239.         paramBlk.accessParam.ioACAccess = 0;
  240.         OSErr err = PBHGetDirAccessSync(¶mBlk);
  241.         
  242.         if (err == noErr) {        /* it is a file share volume, look at the access right */
  243.             if ((paramBlk.accessParam.ioACAccess & 0x04000000) == 0) /* no write access */
  244.                 result = kODTrue;
  245.         }
  246.         else if (err == paramErr) { /* it is not file share, look at directory */
  247.             pbBlock.dirInfo.ioCompletion = kODNULL;
  248.             pbBlock.dirInfo.ioNamePtr = kODNULL;
  249.             pbBlock.dirInfo.ioVRefNum = fFileSpec.vRefNum;
  250.             pbBlock.dirInfo.ioFDirIndex = -1;
  251.             pbBlock.dirInfo.ioDrDirID = fFileSpec.parID;
  252.             pbBlock.dirInfo.ioFlAttrib = 0;
  253.             THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  254.             if (pbBlock.dirInfo.ioFlAttrib & 1)
  255.                 result = kODTrue;
  256.         }
  257.         else
  258.             THROW(err);
  259.     }
  260.  
  261.     // Check to see whether the file is locked
  262.     if (result == kODFalse) {    
  263.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  264.         pbBlock.hFileInfo.ioFDirIndex = 0;
  265.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  266.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  267.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  268.         
  269.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  270.  
  271.         if (pbBlock.hFileInfo.ioFlAttrib & 1)
  272.             result = kODTrue;
  273.     }
  274.     
  275.     return result;
  276. }
  277.  
  278. //------------------------------------------------------------------------------
  279. // PlatformFile::Lock
  280. //------------------------------------------------------------------------------
  281. void PlatformFile::Lock()
  282. {
  283.     THROW_IF_ERROR( FSpSetFLock(&fFileSpec) );
  284. }
  285.  
  286. //------------------------------------------------------------------------------
  287. // PlatformFile::Unlock
  288. //------------------------------------------------------------------------------
  289. void PlatformFile::Unlock()
  290. {
  291.     THROW_IF_ERROR( FSpRstFLock(&fFileSpec) );
  292. }
  293.  
  294.  
  295. //------------------------------------------------------------------------------
  296. // PlatformFile::IsStationery
  297. //------------------------------------------------------------------------------
  298. ODBoolean PlatformFile::IsStationery()
  299. {
  300.     FInfo fileInfo;
  301.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec,&fileInfo) );
  302.     return (((fileInfo.fdFlags)&kIsStationary)!=0);
  303. }
  304.  
  305. //------------------------------------------------------------------------------
  306. // PlatformFile::SetStationery
  307. //------------------------------------------------------------------------------
  308. void PlatformFile::SetStationery(ODBoolean isStationery)
  309. {
  310.     FInfo fileInfo;
  311.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec,&fileInfo) );
  312.     if (isStationery)
  313.         (fileInfo.fdFlags) |= kIsStationary;
  314.     else
  315.         (fileInfo.fdFlags) &= ~kIsStationary;
  316.     THROW_IF_ERROR( FSpSetFInfo(&fFileSpec,&fileInfo) );
  317.     BumpFolderModDate();
  318. }
  319.  
  320.  
  321. //------------------------------------------------------------------------------
  322. // PlatformFile::SetCustomIcon
  323. //------------------------------------------------------------------------------
  324. void PlatformFile::SetCustomIcon(ODBoolean hasCustomIcon)
  325. {
  326.     FInfo fileInfo;
  327.  
  328.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  329.     if (hasCustomIcon)
  330.         (fileInfo.fdFlags) |= kHasCustomIcon;
  331.     else
  332.         (fileInfo.fdFlags) &= ~kHasCustomIcon;
  333.     THROW_IF_ERROR( FSpSetFInfo(&fFileSpec, &fileInfo) );
  334.     BumpFolderModDate();
  335. }
  336.  
  337. //------------------------------------------------------------------------------
  338. // PlatformFile::HasCustomIcon
  339. //------------------------------------------------------------------------------
  340. ODBoolean PlatformFile::HasCustomIcon()
  341. {
  342.     FInfo fileInfo;
  343.  
  344.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  345.     return (fileInfo.fdFlags &= kHasCustomIcon ? kODTrue : kODFalse);
  346. }
  347.  
  348. //------------------------------------------------------------------------------
  349. // PlatformFile::IsDirectory
  350. //------------------------------------------------------------------------------
  351. ODBoolean PlatformFile::IsDirectory()
  352. {    
  353.     ODBoolean isDirectory = kODFalse;
  354.     
  355.     if( fFileID == kODNoFileID ) {
  356.         CInfoPBRec    pbBlock;
  357.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  358.         pbBlock.hFileInfo.ioFDirIndex = 0;
  359.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  360.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  361.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  362.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  363.         isDirectory = pbBlock.dirInfo.ioFlAttrib & 0x10 ? kODTrue : kODFalse;
  364.     }
  365.     return isDirectory;
  366. }
  367.  
  368. //------------------------------------------------------------------------------
  369. // PlatformFile::IsEqualTo
  370. //------------------------------------------------------------------------------
  371. ODBoolean PlatformFile::IsEqualTo(PlatformFile* file)
  372. {
  373.     return (fFileSpec.parID == file->fFileSpec.parID &&
  374.             fFileSpec.vRefNum == file->fFileSpec.vRefNum &&
  375.             EqualPascalStrings(fFileSpec.name, file->fFileSpec.name));
  376. }
  377.  
  378. //------------------------------------------------------------------------------
  379. // PlatformFile::GetFInfoFlags
  380. //------------------------------------------------------------------------------
  381. ODUShort    PlatformFile::GetFInfoFlags()
  382. {
  383.     FInfo fileInfo;
  384.  
  385.     THROW_IF_ERROR( FSpGetFInfo(&fFileSpec, &fileInfo) );
  386.     return fileInfo.fdFlags;
  387. }
  388.  
  389. //------------------------------------------------------------------------------
  390. // PlatformFile::Create
  391. //------------------------------------------------------------------------------
  392. void PlatformFile::Create(ODOSType creator, ODOSType fileType, ODScriptCode scriptCode)
  393. {    
  394.     
  395.     if (fDataRefNum == kODNoFileRefNum) {
  396.         THROW_IF_ERROR( FSpCreate(&fFileSpec, creator, fileType, scriptCode) );
  397.     }
  398.     fCreator = creator;
  399.     fFileType = fileType;
  400.     fScriptTag = scriptCode;
  401.     
  402.     this->GetFileID();
  403. }
  404.  
  405. //------------------------------------------------------------------------------
  406. // PlatformFile::CreateResFile
  407. //------------------------------------------------------------------------------
  408. void PlatformFile::CreateResFile()
  409. {
  410.     if (fResRefNum == kODNoFileRefNum)
  411.     {
  412.         FSpCreateResFile(&fFileSpec, fCreator, fFileType, fScriptTag);
  413.         THROW_IF_ERROR(ResError());
  414.     }
  415.     this->GetFileID();
  416. }
  417.  
  418. //------------------------------------------------------------------------------
  419. // PlatformFile::OpenResFile
  420. //------------------------------------------------------------------------------
  421. void PlatformFile::OpenResFile()
  422. {
  423.     ASSERT(fResOpenStack >= 0, kODErrAssertionFailed);
  424.     if (fResRefNum == kODNoFileRefNum)
  425.     {
  426.         ASSERT(fResOpenStack == 0, fResOpenStack);
  427.         fResRefNum = GetFirstLocalPath(PlatformFile::kODResourceFork);
  428.         if (fResRefNum != kODNoFileRefNum)
  429.         {
  430.             // Resource fork is already open
  431.             UseResFile(fResRefNum);
  432.             fNeedToClose = kODFalse;
  433.         }
  434.         else
  435.         {
  436.             // Resource fork is closed
  437.             fResRefNum = FSpOpenResFile(&fFileSpec, fPermission);
  438.             if (fResRefNum == -1 && fPermission != fsRdPerm)
  439.             {
  440.                 fResRefNum = kODNoFileRefNum;
  441.                 CreateResFile();
  442.                 fResRefNum = FSpOpenResFile(&fFileSpec, fPermission);
  443.             }
  444.             OSErr err = ResError();
  445.             if (err != eofErr)
  446.             {
  447.                 if (fResRefNum == -1)
  448.                     fResRefNum = kODNoFileRefNum;
  449.                 THROW_IF_ERROR(ResError());
  450.             }
  451.             if (fResRefNum == -1)
  452.             {
  453.                 fResRefNum = kODNoFileRefNum;
  454.                 THROW(resFNotFound);
  455.             }
  456.             fNeedToClose = kODTrue;
  457.         }
  458.     }
  459.     else
  460.         UseResFile(fResRefNum);
  461.     ++fResOpenStack;
  462. }
  463.  
  464. //------------------------------------------------------------------------------
  465. // PlatformFile::CloseResFile
  466. //------------------------------------------------------------------------------
  467. void PlatformFile::CloseResFile()
  468. {
  469.     ASSERT(fResOpenStack > 0, fResOpenStack);
  470.     if (--fResOpenStack == 0 && fNeedToClose)
  471.     {
  472.         ::CloseResFile(fResRefNum);
  473.         THROW_IF_ERROR(ResError());
  474.         fResRefNum = kODNoFileRefNum;
  475.     }
  476. }
  477.  
  478. //------------------------------------------------------------------------------
  479. // PlatformFile::GetFileID
  480. //------------------------------------------------------------------------------
  481. void PlatformFile::GetFileID()
  482. {
  483.     if( fFileID == kODNoFileID ) {
  484.         CInfoPBRec    pbBlock;
  485.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  486.         pbBlock.hFileInfo.ioFDirIndex = 0;
  487.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  488.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  489.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  490.         THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  491.         fFileID = pbBlock.hFileInfo.ioDirID;    /* for tracking the file later */
  492.     }
  493. }
  494.  
  495. //------------------------------------------------------------------------------
  496. // PlatformFile::UpdateSpecFromID
  497. //------------------------------------------------------------------------------
  498. void PlatformFile::UpdateSpecFromID()
  499. {
  500.     if (fFileID != kODNoFileID) {    /* make sure got the latest name in file spec */
  501.         HParamBlockRec hPB;
  502.         hPB.fidParam.ioCompletion = kODNULL;
  503.         hPB.fidParam.ioNamePtr = fFileSpec.name;
  504.         hPB.fidParam.ioVRefNum = fFileSpec.vRefNum;
  505.         hPB.fidParam.ioFileID = fFileID;
  506.         if (PBResolveFileIDRefSync(&hPB) == noErr)    /* ignore any error */
  507.             fFileSpec.parID = hPB.fidParam.ioSrcDirID;
  508.     }
  509. }
  510.  
  511.  
  512. //------------------------------------------------------------------------------
  513. // PlatformFile::Exists
  514. //------------------------------------------------------------------------------
  515. ODBoolean PlatformFile::Exists()
  516. {
  517.     const ODFileSpec &filespec = this->GetFileSpec();
  518.     FInfo ignore ;
  519.     OSErr err = FSpGetFInfo( &filespec, &ignore );
  520.     if ( err == noErr )
  521.         return kODTrue ;
  522.     else {
  523.         if ( err != fnfErr )
  524.             THROW( err );
  525.         return kODFalse ;
  526.     }
  527. }
  528.  
  529. //------------------------------------------------------------------------------
  530. // PlatformFile::Open
  531. //------------------------------------------------------------------------------
  532. void PlatformFile::Open()
  533. {    
  534.     if (fDataRefNum == kODNoFileRefNum) {
  535.         this->GetFileID();
  536.         THROW_IF_ERROR(FSpOpenDF(&fFileSpec, fPermission, &fDataRefNum));
  537.     }
  538.     else
  539.         THROW(kODErrFileOpened);
  540. }
  541.  
  542. //------------------------------------------------------------------------------
  543. // PlatformFile::Close
  544. //------------------------------------------------------------------------------
  545. void PlatformFile::Close()
  546. {    
  547.     if (fDataRefNum != kODNoFileRefNum) {
  548.         THROW_IF_ERROR(FSClose(fDataRefNum));
  549.         fDataRefNum = kODNoFileRefNum;
  550.     }
  551.     else
  552.         THROW(kODErrFileClosed);
  553. }
  554.  
  555. //------------------------------------------------------------------------------
  556. // PlatformFile::Delete
  557. //------------------------------------------------------------------------------
  558. void PlatformFile::Delete()
  559. {    
  560.     THROW_IF_ERROR(FSpDelete(&fFileSpec));
  561.     fFileID = kODNoFileID;
  562. }
  563.  
  564.  
  565. //------------------------------------------------------------------------------
  566. // PlatformFile::FlushVolume
  567. //------------------------------------------------------------------------------
  568. void PlatformFile::FlushVolume()
  569. {    
  570.     if (fDataRefNum != kODNoFileRefNum) {
  571.         ParamBlockRec    pb;
  572.     
  573.         pb.ioParam.ioCompletion = kODNULL;
  574.         pb.ioParam.ioRefNum = fDataRefNum;
  575.         (void) PBFlushFileSync(&pb);
  576.     }
  577.  
  578.     (void) FlushVol(kODNULL, fFileSpec.vRefNum);
  579. }
  580.  
  581. //------------------------------------------------------------------------------
  582. // PlatformFile::SetFilePos
  583. //------------------------------------------------------------------------------
  584. void PlatformFile::SetFilePos(ODSShort posMode, ODSLong posOff)
  585. {    
  586.     THROW_IF_ERROR(SetFPos(fDataRefNum, posMode, posOff));
  587. }
  588.  
  589. //------------------------------------------------------------------------------
  590. // PlatformFile::GetFilePos
  591. //------------------------------------------------------------------------------
  592. ODSLong PlatformFile::GetFilePos()
  593. {
  594.     ODSLong    posOff;
  595.     
  596.     THROW_IF_ERROR(GetFPos(fDataRefNum, &posOff));
  597.     return posOff;
  598. }
  599.  
  600. //------------------------------------------------------------------------------
  601. // PlatformFile::Read
  602. //------------------------------------------------------------------------------
  603. void PlatformFile::Read(void* buffer, ODSLong* count)
  604. {    
  605.     THROW_IF_ERROR(FSRead(fDataRefNum, count, buffer));
  606. }
  607.  
  608. //------------------------------------------------------------------------------
  609. // PlatformFile::Write
  610. //------------------------------------------------------------------------------
  611. void PlatformFile::Write(const void* buffer, ODSLong* count)
  612. {    
  613.     THROW_IF_ERROR(FSWrite(fDataRefNum, count, buffer));
  614. }
  615.  
  616. //------------------------------------------------------------------------------
  617. // PlatformFile::GetEndOfFile
  618. //------------------------------------------------------------------------------
  619. ODSLong PlatformFile::GetEndOfFile()
  620. {    
  621.     ODSLong    length;
  622.     
  623.     THROW_IF_ERROR(GetEOF(fDataRefNum, &length));
  624.     return length;
  625. }
  626.  
  627. //------------------------------------------------------------------------------
  628. // PlatformFile::SetEndOfFile
  629. //------------------------------------------------------------------------------
  630. void  PlatformFile::SetEndOfFile(ODSLong length)
  631. {    
  632.     THROW_IF_ERROR(SetEOF(fDataRefNum, length));
  633. }
  634.  
  635. //------------------------------------------------------------------------------
  636. // PlatformFile::GetName
  637. //------------------------------------------------------------------------------
  638. ODName* PlatformFile::GetName()
  639. {
  640.     this->UpdateSpecFromID();
  641.  
  642.     return CreateIText(fScriptTag, 0, fFileSpec.name);
  643. }
  644.  
  645. //------------------------------------------------------------------------------
  646. // PlatformFile::GetAsciiName
  647. //------------------------------------------------------------------------------
  648. void PlatformFile::GetAsciiName(char* asciiName, ODULong maxLength)
  649. {
  650.     this->UpdateSpecFromID();
  651.  
  652.     ODULong n = fFileSpec.name[0];
  653.     if( n > maxLength )
  654.         n = maxLength;
  655.     ODBlockMove(&(fFileSpec.name[1]), asciiName, n);
  656.     asciiName[n] = '\0';
  657. }
  658.  
  659. //------------------------------------------------------------------------------
  660. // PlatformFile::GetPlatformCreator
  661. //------------------------------------------------------------------------------
  662. ODOSType PlatformFile::GetPlatformCreator()
  663. {
  664.     if (fCreator == kBogusOSType) {
  665.         FInfo    fileInfo;
  666.         THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  667.         fCreator = fileInfo.fdCreator;
  668.         fFileType = fileInfo.fdType;
  669.     }
  670.     return fCreator;
  671. }    
  672.  
  673. //------------------------------------------------------------------------------
  674. // PlatformFile::GetPlatformType
  675. //------------------------------------------------------------------------------
  676. ODOSType PlatformFile::GetPlatformType()
  677. {
  678.     if (fFileType == kBogusOSType) {
  679.         FInfo    fileInfo;
  680.         THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  681.         fCreator = fileInfo.fdCreator;
  682.         fFileType = fileInfo.fdType;
  683.     }
  684.     return fFileType;
  685. }    
  686.  
  687. //------------------------------------------------------------------------------
  688. // PlatformFile::SetPlatformType
  689. //------------------------------------------------------------------------------
  690. void PlatformFile::SetPlatformType(ODOSType fileType)
  691. {
  692.     FInfo    fileInfo;
  693.     THROW_IF_ERROR(FSpGetFInfo(&fFileSpec, &fileInfo));
  694.     if( fileInfo.fdType != fileType ) {
  695.         fileInfo.fdType = fileType;
  696.         THROW_IF_ERROR(FSpSetFInfo(&fFileSpec, &fileInfo));
  697.         fFileType = fileType;
  698.         this->BumpFolderModDate();
  699.     }
  700. }    
  701.  
  702.  
  703. //------------------------------------------------------------------------------
  704. // PlatformFile::GetContainerType
  705. //------------------------------------------------------------------------------
  706.  
  707. ODContainerType PlatformFile::GetContainerType()
  708. {
  709.     if (fContainerType == kODNULL)
  710.         fContainerType =
  711.             (ODContainerType)
  712.             (this->ReadResourcePtr(kFileContainerType, kFileContainerTypeResID, kODNULL));
  713.  
  714.     return fContainerType;
  715. }
  716.  
  717. //------------------------------------------------------------------------------
  718. // PlatformFile::SetContainerType
  719. //------------------------------------------------------------------------------
  720.  
  721. void PlatformFile::SetContainerType(ODContainerType containerType)
  722. {
  723.     ODDisposePtr(fContainerType);
  724.     fContainerType = containerType;
  725.  
  726.     this->WriteResourcePtr(kFileContainerType, kFileContainerTypeResID, 
  727.                         (ODPtr)containerType, strlen(containerType)+1);
  728. }
  729.  
  730.  
  731. //------------------------------------------------------------------------------
  732. // CWithActiveResources class
  733. //------------------------------------------------------------------------------
  734.  
  735. class CWithActiveResources :Destructo {
  736.     public:
  737.     CWithActiveResources( PlatformFile* );
  738.    ~CWithActiveResources( );
  739.     private:
  740.     PlatformFile    *fFile;
  741.     ODFileRefNum    fCurResFile;
  742.     ODBoolean        fSuccessfullyOpened;
  743. };
  744.  
  745. CWithActiveResources::CWithActiveResources( PlatformFile *pf )
  746. {
  747.     fSuccessfullyOpened = kODFalse;
  748.     fFile = pf;
  749.     fCurResFile = CurResFile();
  750.     fFile->OpenResFile();
  751.     fSuccessfullyOpened = kODTrue;
  752. }
  753.  
  754. CWithActiveResources::~CWithActiveResources( )
  755. {
  756.     if (fSuccessfullyOpened)
  757.         fFile->CloseResFile();
  758.     UseResFile(fCurResFile);
  759. }
  760.         
  761.  
  762. //------------------------------------------------------------------------------
  763. // PlatformFile::ReadResourcePtr
  764. //------------------------------------------------------------------------------
  765. ODPtr PlatformFile::ReadResourcePtr(ODPlatformType resType, ODSShort resID, ODULong* size)
  766. {
  767.     ODPtr resPtr = kODNULL;     ODVolatile(resPtr);    // Method Specific
  768.     
  769.     TRY
  770.         CWithActiveResources w(this); // this throws if no resfile
  771.         
  772.         Handle resHandle = Get1Resource(resType, resID);
  773.         if (resHandle != kODNULL)
  774.         {
  775.             HNoPurge(resHandle);
  776.             ODULong hsize = GetHandleSize(resHandle);
  777.             if (size != kODNULL)
  778.                 *size = hsize;
  779.             resPtr = ODNewPtrClear(hsize,0);
  780.             ODBlockMove(*resHandle,resPtr, hsize);
  781.             ReleaseResource(resHandle);
  782.         } else if( ResError() != resNotFound )
  783.             THROW_IF_ERROR(ResError());
  784.  
  785.     CATCH_ALL
  786.     ENDTRY
  787.     
  788.     return resPtr;  // Method Specific
  789. }
  790.  
  791. //------------------------------------------------------------------------------
  792. // PlatformFile::WriteResourcePtr
  793. //------------------------------------------------------------------------------
  794. void PlatformFile::WriteResourcePtr(ODPlatformType resType, ODSShort resID, 
  795.                                     const void *resPtr, ODULong size)
  796. {
  797.     ASSERT(resPtr!=kODNULL,kODErrIllegalNullInput);
  798.     
  799.     SetPermission(fsRdWrPerm);
  800.     CWithActiveResources w(this);
  801.     
  802.     Handle resHandle = Get1Resource(resType,resID);
  803.     if( ResError() != resNotFound )
  804.         THROW_IF_ERROR(ResError());
  805.         
  806.     ODBoolean needsAdding = (resHandle == kODNULL);
  807.     if (needsAdding)
  808.         resHandle = ODNewHandle(size);
  809.     else {
  810.         HNoPurge(resHandle);
  811.         ODSetHandleSize(resHandle, size);
  812.     }
  813.     
  814.     ODBlockMove(resPtr,*resHandle, size);
  815.     
  816.     if (needsAdding)
  817.         AddResource(resHandle,resType,resID,"\p");
  818.     else
  819.         ChangedResource(resHandle);
  820.     THROW_IF_ERROR(ResError());
  821. }
  822.  
  823.  
  824. //------------------------------------------------------------------------------
  825. // PlatformFile::DeleteResource
  826. //------------------------------------------------------------------------------
  827. void PlatformFile::DeleteResource(ODPlatformType resType, ODSShort resID)
  828. {
  829.     SetPermission(fsRdWrPerm);
  830.     CWithActiveResources w(this);
  831.     
  832.     Handle resHandle = Get1Resource(resType, resID);
  833.     OSErr err= ResError();
  834.     if( resHandle ) {
  835.         RemoveResource(resHandle);
  836.         err= ResError();
  837.         if( !err )
  838.             DisposeHandle(resHandle);    // After RemoveResource it's not a rsrc
  839.     } else {
  840.         if( err == resNotFound )
  841.             err = noErr;
  842.     }
  843.     THROW_IF_ERROR(err);
  844. }
  845.  
  846. //------------------------------------------------------------------------------
  847. // PlatformFile::GetAllocationBlockSize
  848. //------------------------------------------------------------------------------
  849. ODULong PlatformFile::GetAllocationBlockSize()
  850. {
  851.     HParamBlockRec pb;
  852.     
  853.     pb.volumeParam.ioCompletion = kODNULL;
  854.     pb.volumeParam.ioNamePtr = kODNULL;
  855.     pb.volumeParam.ioVRefNum = fFileSpec.vRefNum;
  856.     pb.volumeParam.ioVolIndex = 0;
  857.  
  858.     THROW_IF_ERROR(PBHGetVInfoSync(&pb));
  859.  
  860.     return pb.volumeParam.ioVAlBlkSiz;
  861. }
  862.  
  863. //------------------------------------------------------------------------------
  864. // PlatformFile::CopyFrom
  865. //------------------------------------------------------------------------------
  866. void PlatformFile::CopyFrom( PlatformFile* src )
  867. {
  868.     ODBoolean srcIsOpen = (src->GetFileRefNum() != kODNoFileRefNum);
  869.     if ( !srcIsOpen )
  870.         src->Open();
  871.     this->SetPermission( fsRdWrPerm );        // currently this is the default value
  872.     if (!this->Exists())
  873.         this->Create(src->GetPlatformCreator(), src->GetPlatformType(), 0 /*$$$$$ scriptcode?*/);
  874.  
  875.     this->Open();
  876.             
  877.     src->SetFilePos( fsFromStart, 0 );
  878.     this->SetFilePos( fsFromStart, 0 );
  879.     
  880.     ODSLong bytesLeft = src->GetEndOfFile();
  881.  
  882.     TempODHandle hbuffer = kODNULL;
  883.     ODSLong bufferSize = kMaxCopyBufferSize;
  884.     if( bufferSize > bytesLeft )
  885.         bufferSize = bytesLeft;
  886.     for( ; bufferSize>=kMinCopyBufferSize; bufferSize /= 2 ) {
  887.         OSErr err;
  888.         hbuffer= TempNewHandle(bufferSize,&err);
  889.         if( hbuffer ) break;
  890.     }
  891.     WASSERT(bufferSize > 0);
  892.     THROW_IF_NULL(hbuffer);
  893.     void *buffer = *hbuffer;
  894.     
  895.     ODSLong count;
  896.  
  897.     while( bytesLeft > 0 )
  898.     {
  899.         count = bytesLeft < bufferSize? bytesLeft: bufferSize ;
  900.         WASSERT(count > 0);
  901.         src->Read( buffer, &count );
  902.         this->Write( buffer, &count );
  903.         bytesLeft -= count ;
  904.     }
  905.     
  906.     if ( !srcIsOpen )
  907.         src->Close();
  908.     this->Close();
  909. }
  910.  
  911. //------------------------------------------------------------------------------
  912. // PlatformFile::MoveRename
  913. //------------------------------------------------------------------------------
  914. void PlatformFile::MoveRename( ODFileSpec* newSpec, ODBoolean isDuplicate )
  915. {
  916.     // This will fail if a file with the old name already exists in the
  917.     // target directory. MoreFiles (DTS) has a more robust version of this.
  918.     
  919.     ASSERT(newSpec->vRefNum == fFileSpec.vRefNum, kODErrAssertionFailed);
  920.  
  921.     if ( isDuplicate )
  922.     {
  923.         THROW_IF_ERROR( FSpDelete( newSpec ) ); 
  924.     }
  925.  
  926.     this->Move( newSpec->parID );
  927.     this->Rename( newSpec->name );
  928. }    // MoveRename()
  929.  
  930.  
  931. //------------------------------------------------------------------------------
  932. // PlatformFile::Move
  933. //------------------------------------------------------------------------------
  934.  
  935. void PlatformFile::Move( ODSLong targetParID )
  936. {
  937.     CMovePBRec paramBlock ;
  938.     memset( ¶mBlock, 0, sizeof(paramBlock) );
  939.     
  940.     paramBlock.ioNamePtr = fFileSpec.name ;
  941.     paramBlock.ioVRefNum = fFileSpec.vRefNum ;
  942.     paramBlock.ioNewDirID = targetParID ;
  943.     paramBlock.ioDirID = fFileSpec.parID ;
  944.     
  945.     (void) HDelete(fFileSpec.vRefNum,targetParID,fFileSpec.name);     // ignore error (may not exist)
  946.     OSErr err = PBCatMoveSync( ¶mBlock );
  947.     THROW_IF_ERROR( err );
  948.  
  949.     fFileSpec.parID = targetParID ;
  950. }
  951.  
  952. //------------------------------------------------------------------------------
  953. // PlatformFile::UniquifyName
  954. // Given in this a platformfile (whose filespec only is used) that may conflict
  955. // with an existing file, deal with this conflict in one of two ways depending
  956. // on the value of action.  The two values are:
  957. // 1. kSpecifyNewNameOnly: just change the name field of the filespec so that the
  958. // platform file represents a file that would be unique if created
  959. // 2. kRenameInPlace: this file already exists, but we want it to have a different
  960. // name so we can reuse this one.  Find that name, and rename the actual file.
  961. // 
  962. // Two string templates are expected, and the caller can either pass in their
  963. // resource IDs or StringHandles to the strings themselves, signifying the latter
  964. // with a resource ID of kODNoResourceID.  The first of these strings is used
  965. // the first time through the renaming loop (which typically sticks something
  966. // like " copy" on the end of the file name, and the second is used thereafter
  967. // (when increasingly large numbers are put into the string in an attempt to
  968. // make it unique.
  969. //------------------------------------------------------------------------------
  970.  
  971. void PlatformFile::UniquifyName( ODSShort uniquifyingStringID,
  972.             StringHandle uniquifyingString, 
  973.             ODSShort uniquifyingNumberID,
  974.             StringHandle uniquifyingNumberString, 
  975.             short copyCount,
  976.             PFUniquifyAction action, 
  977.             ODBoolean forceNewName)
  978. {
  979.     if ((forceNewName!=kODTryCurrentName) || this->Exists() )
  980.     {
  981.         PlatformFile* possibleOther = new PlatformFile;
  982.         TempPlatformFile t = possibleOther;        // save so will get deconstructed
  983. //        possibleOther->SpecifyFromFile( this );
  984.     
  985.         // Get the strings to be used in substitution if they weren't passed in.
  986.         // Assign them to tempobjs so we don't have to dispose later.  Don't assign
  987.         // if they're passed in (of course....)
  988.         TempODHandle registerNoNumHandleIfLocal = kODNULL;
  989.         TempODHandle registerNumHandleIfLocal = kODNULL;
  990.         CUsingLibraryResources r;
  991.         if ( uniquifyingStringID != kODNoResourceID )
  992.         {
  993.             WASSERT( !uniquifyingString );
  994.             uniquifyingString = GetString( uniquifyingStringID );
  995.             DetachResource( (Handle)uniquifyingString );
  996.             registerNoNumHandleIfLocal = (Handle)uniquifyingString;
  997.             WASSERT( uniquifyingString );
  998.         }
  999.         if ( uniquifyingNumberID != kODNoResourceID )
  1000.         {
  1001.             WASSERT(!uniquifyingNumberString);
  1002.             uniquifyingNumberString = GetString( uniquifyingNumberID );
  1003.             DetachResource( (Handle)uniquifyingNumberString );
  1004.             registerNumHandleIfLocal = (Handle)uniquifyingNumberString;
  1005.         }
  1006.         WASSERT(uniquifyingNumberString);
  1007.     
  1008.         ODFileSpec localCopy = this->GetFileSpec();
  1009.         // save the name (as we'll be munging localCopy)
  1010.         Str63 originalName;
  1011.         ODBlockMove( localCopy.name, originalName, localCopy.name[0]+1 );
  1012.     
  1013.         TempODHandle baseText = ODNewHandle(kMaxFileNameSize+1);
  1014.         THROW_IF_NULL(baseText);
  1015.         TempODHandle substitutionText = ODNewHandle(kMaxFileNameSize+1);
  1016.         THROW_IF_NULL(substitutionText);
  1017.     
  1018.         ODBoolean nameNeedsNumber = (uniquifyingString == kODNULL);
  1019.             // if there is no uniquifyingString, we immediately need to start using
  1020.             // the uniquifyingNumberString, or in other words nameNeedsNumber==true.
  1021.             
  1022.         for ( ; ; nameNeedsNumber = kODTrue)
  1023.         {
  1024.             // nameNeedsNumber = copyCount > 1;
  1025.             StringHandle templateToUse = nameNeedsNumber ?
  1026.                     uniquifyingNumberString : uniquifyingString;
  1027.     
  1028.             short thisTemplateLen = **templateToUse;
  1029.             // <eeh> NOTE that this forces callers to have two ^number tuples in the
  1030.             // second template.
  1031.             thisTemplateLen -= nameNeedsNumber? 4 : 2;
  1032.     
  1033.             short numberLen;
  1034.             Str32 numberString;
  1035.             if ( nameNeedsNumber )
  1036.             {
  1037.                 NumToString( copyCount, numberString );
  1038.                 numberLen = numberString[0];
  1039.             }
  1040.             else
  1041.                 numberLen = 0;
  1042.     
  1043.             // truncate the name if after appending it will be too long
  1044.             Str63 localName;
  1045.             ODBlockMove( originalName, localName, originalName[0] + 1 );
  1046.             short postAppendLen = localName[0] + thisTemplateLen + numberLen;
  1047.             if ( postAppendLen > kODMaxFileNameSize )
  1048.                 ClipStringToBytes( localName,
  1049.                         kODMaxFileNameSize - thisTemplateLen - numberLen, fScriptTag );
  1050.     
  1051.             // copy the template into the base handle, then pass in the possible file
  1052.             // name
  1053.             short len;
  1054.             SetHandleSize( baseText, len = **templateToUse );
  1055.             ODBlockMove( (*templateToUse)+1, *baseText, len );
  1056.             SetHandleSize( substitutionText, len = localName[0] );
  1057.             ODBlockMove( &localName[1], *substitutionText, len );
  1058.             short err = ReplaceText( baseText, substitutionText, "\p^0" );
  1059.             WASSERT( err >= 0 );
  1060.             
  1061.             if ( nameNeedsNumber )        // do same for number
  1062.             {
  1063.                 SetHandleSize( substitutionText, len = numberString[0] );
  1064.                 ODBlockMove( &numberString[1], *substitutionText, len );
  1065.                 err = ReplaceText( baseText, substitutionText, "\p^1" );
  1066.                 WASSERT( err >= 0 );
  1067.             }
  1068.     
  1069.             ODBlockMove( *baseText, &localCopy.name[1], len = GetHandleSize(baseText) );
  1070.             localCopy.name[0] = len;
  1071.     
  1072.             possibleOther->Specify( &localCopy );
  1073.             if ( !possibleOther->Exists() )
  1074.             {
  1075.                 WASSERT( localCopy.name[0] <= kODMaxFileNameSize );
  1076.                 if ( action == kSpecifyNewNameOnly )
  1077.                 {
  1078.                     // set up this so that when created it will represent a unique file
  1079.                     PascalToCString( localCopy.name );
  1080.                     this->SetAsciiName( (char*)localCopy.name );
  1081.                 }
  1082.                 else if ( action == kRenameInPlace )
  1083.                 {
  1084.                     // put the original file spec back in the target, then call
  1085.                     // Rename passing in the new name
  1086.                     WASSERT(this->Exists());
  1087.                     this->Rename( localCopy.name );
  1088.                 }
  1089.                 else
  1090.                     WARN( "unknown PFUniquifyAction" );
  1091.                 break;
  1092.             }
  1093.             if (nameNeedsNumber)
  1094.                 ++copyCount;        
  1095.                 // Gets executed after 2nd time through loop if there was a valid
  1096.                 // uniquifyString.  
  1097.                 // Otherwise gets executed after 1st time through loop.
  1098.         }
  1099.     }
  1100. }    // UniquifyName
  1101.  
  1102. //------------------------------------------------------------------------------
  1103. // PlatformFile::MoveToTrash
  1104. //------------------------------------------------------------------------------
  1105.  
  1106. void PlatformFile::MoveToTrash()
  1107. {
  1108.     ODSLong parID = fFileSpec.parID;
  1109.     ODSLong            trashDirID;
  1110.     THROW_IF_ERROR(FindFolder(fFileSpec.vRefNum, kTrashFolderType, kCreateFolder,
  1111.                             &(fFileSpec.vRefNum), &trashDirID));
  1112.                             
  1113.     // Move deletes any file that may conflict with the file once moved, but
  1114.     // in this case that isn't what we want.  So check if such a file exists,
  1115.     // and if so rename the conflicting file first (following the Finder's
  1116.     // model.)
  1117.     ODFileSpec possibleOtherFS = this->GetFileSpec();
  1118.     possibleOtherFS.parID = trashDirID;
  1119.     PlatformFile target;        // represents a file that *may* be in the trash
  1120.     target.Specify( &possibleOtherFS );
  1121.     
  1122. #if 1
  1123. //    if ( target.Exists() )
  1124.     {
  1125.         CUsingLibraryResources r;
  1126.         target.UniquifyName( kCopyDefaultNameNoNumStrID, kODNULL,
  1127.                 kCopyDefaultNameWithNumStrID, kODNULL, 2, kRenameInPlace,
  1128.                 kODTryCurrentName ) ;
  1129.     }
  1130. #else
  1131.     Str32 uniqueName;
  1132.     if ( MakeUniqueFileName( &target, kCopyDefaultNameNoNumStrID,
  1133.             kCopyDefaultNameWithNumStrID, 31, uniqueName ) )
  1134.         target.Rename( uniqueName );
  1135. #endif
  1136.     this->Move(trashDirID);
  1137.  
  1138.     CInfoPBRec pbRec;
  1139.     pbRec.hFileInfo.ioCompletion = NULL;
  1140.     pbRec.hFileInfo.ioNamePtr = fFileSpec.name;
  1141.     pbRec.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1142.     pbRec.hFileInfo.ioFDirIndex = 0;
  1143.     pbRec.hFileInfo.ioDirID = fFileSpec.parID;
  1144.     
  1145.     
  1146.     if ( PBGetCatInfoSync( &pbRec ) == noErr )
  1147.     {
  1148.         // <eeh> stuffing this field *may* not work under Copland
  1149.         pbRec.hFileInfo.ioFlXFndrInfo.fdPutAway = parID;
  1150.         // this was changed by PBGetCatInfoSync...
  1151.         pbRec.hFileInfo.ioDirID = fFileSpec.parID;
  1152.         (void)PBSetCatInfoSync( &pbRec );    // ignore the error
  1153.     }
  1154. }
  1155.  
  1156. //------------------------------------------------------------------------------
  1157. // PlatformFile::Rename
  1158. //        This routine will not yet delete a file that will prevent the
  1159. //            renaming (as Move() does above.)
  1160. //------------------------------------------------------------------------------
  1161. void PlatformFile::Rename( Str63 newName )
  1162. {
  1163.     this->UpdateSpecFromID();
  1164.     
  1165.     THROW_IF_ERROR( FSpRename( &fFileSpec, newName ) );
  1166.      CopyPascalString(fFileSpec.name, newName);
  1167.     BumpFolderModDate();
  1168. }
  1169.  
  1170.  
  1171. //------------------------------------------------------------------------------
  1172. // PlatformFile::GetFileModDate
  1173. //        This routine will set the file modification date to the input parameter
  1174. //------------------------------------------------------------------------------
  1175. ODTime PlatformFile::GetFileModDate()
  1176. {
  1177.     this->UpdateSpecFromID();
  1178.     
  1179.     CInfoPBRec    pbBlock;
  1180.     pbBlock.hFileInfo.ioCompletion = kODNULL;
  1181.     pbBlock.hFileInfo.ioFDirIndex = 0;
  1182.     pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1183.     pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1184.     pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1185.     THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  1186.     return pbBlock.hFileInfo.ioFlMdDat;
  1187. }
  1188.  
  1189.  
  1190. //------------------------------------------------------------------------------
  1191. // PlatformFile::SetFileModDate
  1192. //        This routine will set the file modification date to the input parameter
  1193. //------------------------------------------------------------------------------
  1194. void PlatformFile::SetFileModDate(ODTime date)
  1195. {
  1196.     this->UpdateSpecFromID();
  1197.     
  1198.     if (!this->IsLocked()) {
  1199.         CInfoPBRec    pbBlock;
  1200.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  1201.         pbBlock.hFileInfo.ioFDirIndex = 0;
  1202.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1203.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1204.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1205.         if (PBGetCatInfoSync(&pbBlock) == noErr) {
  1206.             pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1207.             pbBlock.hFileInfo.ioFlMdDat = date;
  1208.             (void) PBSetCatInfoSync(&pbBlock); /* who cares if it fails */
  1209.         }
  1210.     }
  1211. }
  1212.  
  1213. //------------------------------------------------------------------------------
  1214. // PlatformFile::SetFileCreationDate
  1215. //        This routine will set the file creation date to the input parameter
  1216. //------------------------------------------------------------------------------
  1217. void PlatformFile::SetFileCreationDate(ODTime date)
  1218. {
  1219.     this->UpdateSpecFromID();
  1220.  
  1221.     CInfoPBRec    pbBlock;
  1222.  
  1223.     if (!this->IsLocked()) {
  1224.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  1225.         pbBlock.hFileInfo.ioFDirIndex = 0;
  1226.         pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1227.         pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1228.         pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1229.         if (PBGetCatInfoSync(&pbBlock) == noErr) {
  1230.             pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1231.             pbBlock.hFileInfo.ioFlCrDat = date;
  1232.             (void) PBSetCatInfoSync(&pbBlock); /* who cares if it fails */
  1233.         }
  1234.     }
  1235. }
  1236.                 
  1237. //------------------------------------------------------------------------------
  1238. // PlatformFile::GetFileCreationDate
  1239. //        This routine will get the file creation date and return it.
  1240. //------------------------------------------------------------------------------
  1241. ODTime PlatformFile::GetFileCreationDate()
  1242. {
  1243.     this->UpdateSpecFromID();
  1244.     
  1245.     CInfoPBRec    pbBlock;
  1246.     pbBlock.hFileInfo.ioCompletion = kODNULL;
  1247.     pbBlock.hFileInfo.ioFDirIndex = 0;
  1248.     pbBlock.hFileInfo.ioNamePtr = fFileSpec.name;
  1249.     pbBlock.hFileInfo.ioVRefNum = fFileSpec.vRefNum;
  1250.     pbBlock.hFileInfo.ioDirID = fFileSpec.parID;
  1251.     THROW_IF_ERROR(PBGetCatInfoSync(&pbBlock));
  1252.     return pbBlock.hFileInfo.ioFlCrDat;
  1253. }
  1254.             
  1255. //------------------------------------------------------------------------------
  1256. // PlatformFile::BumpFolderModDate
  1257. //        This routine will set the file modification date of the parent folder
  1258. //        to the current time so as to cause the Finder to refresh the folder if
  1259. //        it is open.  It only has WARNs if it errors.
  1260. //------------------------------------------------------------------------------
  1261. void PlatformFile::BumpFolderModDate()
  1262. {
  1263.     CInfoPBRec    theParamBlock;
  1264.  
  1265.     memset (&theParamBlock, 0, sizeof(theParamBlock));
  1266.     // ioNamePtr = 0
  1267.     theParamBlock.dirInfo.ioFDirIndex = -1;
  1268.     theParamBlock.dirInfo.ioVRefNum = fFileSpec.vRefNum;
  1269.     theParamBlock.dirInfo.ioDrDirID = fFileSpec.parID;
  1270.     OSErr err = PBGetCatInfoSync(&theParamBlock);
  1271.     if( err )
  1272.         WARN("Couldn't get dir mod date, err %hd",err);
  1273.     else
  1274.     {
  1275.         ODULong newTime;
  1276.  
  1277.         GetDateTime(&newTime);
  1278.         // set to the future if it is now
  1279.         if (theParamBlock.dirInfo.ioDrMdDat >= newTime)
  1280.             ++newTime;
  1281.         theParamBlock.dirInfo.ioDrMdDat = newTime;
  1282.         err = PBSetCatInfoSync(&theParamBlock);
  1283.         if( err )
  1284.             WARN("Couldn't bump dir mod date, err %hd",err);
  1285.     }
  1286. }
  1287.                 
  1288. //------------------------------------------------------------------------------
  1289. // PlatformFile::GetFirstLocalPath
  1290. //------------------------------------------------------------------------------
  1291.  
  1292. ODFileRefNum PlatformFile::GetFirstLocalPath( ODForkType fork )
  1293. {
  1294.     ODFileSpec* spec = &fFileSpec;
  1295.     
  1296.     OSErr        result;
  1297.     FCBPBRec    pb;
  1298.     short        index;
  1299.     Str31        tempName;
  1300.     
  1301.     /* Get FCB name in tempName */
  1302.     pb.ioNamePtr = tempName;
  1303.     
  1304.     /* Index through the open paths on the volume specified by fFileSpec.vRefNum */
  1305.     pb.ioVRefNum = fFileSpec.vRefNum;
  1306.     index = 1;
  1307.     do
  1308.     {
  1309.         pb.ioRefNum = 0;
  1310.         pb.ioFCBIndx = index;
  1311.         result = PBGetFCBInfoSync(&pb);
  1312.         if ( result == noErr )
  1313.         {
  1314.             /*
  1315.             **    See if parent directory ID matches and
  1316.             **    file name matches and
  1317.             **    the file fork (resource or data) matches
  1318.             */
  1319.             if ( (pb.ioFCBParID == fFileSpec.parID) &&
  1320.                  EqualString(fFileSpec.name, tempName, false, true) &&
  1321.                  ((fork == kODResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1322.             {
  1323.                 return pb.ioRefNum;            // Found it!
  1324.             }
  1325.             ++index;    /* next FCB index */
  1326.         }
  1327.     } while ( result == noErr );
  1328.     
  1329.     return kODNoFileRefNum;
  1330. }
  1331.  
  1332.  
  1333. //------------------------------------------------------------------------------
  1334. // PlatformFile::GetLocalPaths
  1335. //------------------------------------------------------------------------------
  1336.  
  1337. ODError        PlatformFile::GetLocalPaths(
  1338.                               ODForkType fork,
  1339.                               ODULong *refNumCount,
  1340.                               ODFileRefNumPtr *refNums)
  1341. {
  1342.     const ODULong kMaxFCBs = 348;    /* The maximum number of local access paths under System 7 */
  1343.     
  1344.     OSErr        result;
  1345.     FCBPBRec    pb;
  1346.     short        index;
  1347.     Str31        tempName;
  1348.     ODFileRefNumPtr    tempRefNums;
  1349.     
  1350.     /* initialize returned values */
  1351.     *refNumCount = 0;
  1352.     *refNums = NULL;
  1353.     
  1354.     /* Allocate temp storage for refNum matches */
  1355.     tempRefNums = (ODFileRefNumPtr)ODNewPtr(kMaxFCBs * sizeof(short));
  1356.     
  1357.     if ( tempRefNums != NULL )
  1358.     {
  1359.         /* Get FCB name in tempName */
  1360.         pb.ioNamePtr = tempName;
  1361.         
  1362.         /* Index through the open paths on the volume specified by fFileSpec.vRefNum */
  1363.         pb.ioVRefNum = fFileSpec.vRefNum;
  1364.         index = 1;
  1365.         do
  1366.         {
  1367.             pb.ioRefNum = 0;
  1368.             pb.ioFCBIndx = index;
  1369.             result = PBGetFCBInfoSync(&pb);
  1370.             if ( result == noErr )
  1371.             {
  1372.                 /*
  1373.                 **    See if parent directory ID matches and
  1374.                 **    file name matches and
  1375.                 **    the file fork (resource or data) matches
  1376.                 */
  1377.                 if ( (pb.ioFCBParID == fFileSpec.parID) &&
  1378.                      EqualString(fFileSpec.name, tempName, false, true) &&
  1379.                      ((fork == kODResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1380.                 {
  1381.                     /* It's a match - add it to the array of matches */
  1382.                     tempRefNums[*refNumCount] = pb.ioRefNum;
  1383.                     ++(*refNumCount);
  1384.                 }
  1385.                 ++index;    /* next FCB index */
  1386.             }
  1387.         } while ( result == noErr );
  1388.         
  1389.         /* These errors are OK - they mean we hit the end of the FCB list */
  1390.         if ( (result == rfNumErr) || (result == fnOpnErr) )
  1391.         {
  1392.             result = noErr;
  1393.         }
  1394.         
  1395.         if ( (result == noErr) && (*refNumCount != 0) )
  1396.         {
  1397.             // Note: the below two lines were a gratuitous change from the tested code
  1398.             // given to me by Jim Luther.  Therefore I have commented them out and returned
  1399.             // the original code. -Tantek
  1400.             //*refNums = (ODFileRefNumPtr) ODReallocate( tempRefNums, *refNumCount * sizeof(short) );
  1401.             //*tempRefNums = kODNULL;
  1402.             /* Allocate memory to return refNum matches in */
  1403.             *refNums = (ODFileRefNumPtr)ODNewPtr(*refNumCount * sizeof(short));
  1404.             if ( *refNums != NULL )
  1405.             {
  1406.                 /* Move refNums from tempRefNums to *refNums */
  1407.                 ODBlockMove((Ptr)tempRefNums, (Ptr)*refNums, (*refNumCount * sizeof(short)));
  1408.             }
  1409.             else
  1410.             {
  1411.                 /* Couldn't allocate memory for refNum array */
  1412.                 result = memFullErr;
  1413.             }
  1414.  
  1415.         }
  1416.         
  1417.         /* Free up tempRefNums storage */ 
  1418.         ODDisposePtr((Ptr)tempRefNums);
  1419.     }
  1420.     else
  1421.     {
  1422.         /* Couldn't allocate temp memory */
  1423.         result = memFullErr;
  1424.     }
  1425.     
  1426.     return ( result );
  1427. }
  1428.  
  1429. //------------------------------------------------------------------------------
  1430. // PlatformFile::GetComments
  1431. //
  1432. //    If a pointer is passed in, the text is placed there and a pointer to it is
  1433. //    returned.  If the comments pointer is null, then a new pointer is allocated
  1434. //    and returned.
  1435. //------------------------------------------------------------------------------
  1436.  
  1437. enum {
  1438.     uppPBDTInfo = kRegisterBased
  1439.          | RESULT_SIZE(sizeof(OSErr))
  1440.          | REGISTER_RESULT_LOCATION(kRegisterD0)
  1441.          
  1442.          | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(kTwoByteCode))    // trap word
  1443.          | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(kTwoByteCode))    // selector
  1444.          
  1445.          | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(DTPBRec*)))
  1446.          | REGISTER_ROUTINE_PARAMETER(4, kRegisterA3, SIZE_CODE(sizeof(void*)))
  1447. };
  1448.  
  1449. #if GENERATING68K && GENERATINGCFM
  1450. OSErr PBDTGetCommentSyncGlue(DTPBRec *pb);
  1451. OSErr PBDTGetCommentSyncGlue(DTPBRec *pb)
  1452. {
  1453.     void* hfsdispatch = GetOSTrapAddress(0xA260);
  1454.     return CallOSTrapUniversalProc((UniversalProcPtr) hfsdispatch,
  1455.                                     uppPBDTInfo,
  1456.                                     (short) 0xA260,    // trap word
  1457.                                     (short) 0x002A,    // selector
  1458.                                     pb,                // a1, the param block ptr
  1459.                                     pb                // a3 should be ignored
  1460.                                   );
  1461. }
  1462. #endif
  1463.  
  1464. #if GENERATING68K && GENERATINGCFM
  1465. OSErr PBDTSetCommentSyncGlue(DTPBRec *pb);
  1466. OSErr PBDTSetCommentSyncGlue(DTPBRec *pb)
  1467. {
  1468.     void* hfsdispatch = GetOSTrapAddress(0xA260);
  1469.     return CallOSTrapUniversalProc((UniversalProcPtr) hfsdispatch,
  1470.                                     uppPBDTInfo,
  1471.                                     (short) 0xA260,    // trap word
  1472.                                     (short) 0x0028,    // selector
  1473.                                     pb,                // a1, the param block ptr
  1474.                                     pb                // a3 should be ignored
  1475.                                   );
  1476. }
  1477. #endif
  1478.  
  1479. ODIText*    PlatformFile::GetComments(ODIText* comments)
  1480. {
  1481.     DTPBRec            pb;    
  1482.     memset( &pb, 0, sizeof(pb) );
  1483.     
  1484.     pb.ioVRefNum = fFileSpec.vRefNum;
  1485.     OSErr err = PBDTGetPath(&pb);
  1486.     if (err == noErr)
  1487.     {
  1488.         pb.ioNamePtr = fFileSpec.name;
  1489.         pb.ioDirID = fFileSpec.parID;
  1490.         char buffer[256];
  1491.         pb.ioDTBuffer = buffer;
  1492.  
  1493.         // avoid the crash on 68K if the PlatformFile is remote
  1494. #if GENERATING68K && GENERATINGCFM
  1495.         err = PBDTGetCommentSyncGlue(&pb);
  1496. #else
  1497.         err = PBDTGetCommentSync(&pb);
  1498. #endif
  1499.         if (err == noErr) {
  1500.             buffer[pb.ioDTActCount] = 0; // make it a c string
  1501.             if (comments == kODNULL)
  1502.             {
  1503.                 ODScriptCode script = FontToScript( GetSysFont() );
  1504.                 comments = CreateITextCString(script, 
  1505.                         GetScriptVariable( script, smScriptLang ), buffer);
  1506.             }
  1507.             else
  1508.                 SetITextCString(comments, buffer);
  1509.         }
  1510.     }
  1511.     
  1512.     return comments;
  1513. }
  1514.  
  1515. //------------------------------------------------------------------------------
  1516. // PlatformFile::SetComments
  1517. //------------------------------------------------------------------------------
  1518.  
  1519. void
  1520. PlatformFile::SetComments(ODIText* comments)
  1521. {
  1522.     DTPBRec        pb;
  1523.     OSErr        err = noErr;    // PBDTGetPath seems not to return anything,
  1524.                                 // so must init
  1525.     
  1526.     if (comments) // <eeh> --> prevents removing 'em: && GetITextStringLength(comments) > 0)
  1527.     {
  1528.         pb.ioNamePtr = kODNULL;
  1529.         pb.ioVRefNum = fFileSpec.vRefNum;
  1530.         err = PBDTGetPath(&pb);
  1531.         if (err == noErr)
  1532.         {
  1533.             pb.ioNamePtr = fFileSpec.name;
  1534.             pb.ioDirID = fFileSpec.parID;
  1535.             pb.ioDTBuffer = GetITextPtr(comments);
  1536.             pb.ioDTReqCount = GetITextStringLength(comments);
  1537.             // avoid the crash on 68K if the PlatformFile is remote
  1538. #if GENERATING68K && GENERATINGCFM
  1539.             err = PBDTSetCommentSyncGlue(&pb);
  1540. #else
  1541.             err = PBDTSetCommentSync(&pb);
  1542. #endif
  1543.         }
  1544.     }
  1545. }
  1546.  
  1547. //------------------------------------------------------------------------------
  1548. // PlatformFile::GetCustomIconFamily
  1549. //------------------------------------------------------------------------------
  1550.  
  1551. ODIconFamily
  1552. PlatformFile::GetCustomIconFamily()
  1553. {
  1554.     ODIconFamily icons = kODNULL;
  1555.     
  1556.     if (HasCustomIcon())
  1557.     {
  1558.         // read icons from the file
  1559.         SetPermission(fsRdPerm);
  1560.         OpenResFile();
  1561.         TRY
  1562.             for( long i=5; i>=0; i-- )
  1563.             {
  1564.                 ODPtr    ptr;
  1565.                 Handle    icon;
  1566.                 ODULong    size;
  1567.                 
  1568.                 ptr = ReadResourcePtr(kIconType[i], kCustomIconResource, &size);
  1569.                 if (ptr != kODNULL)
  1570.                 {
  1571.                     if (icons == kODNULL)
  1572.                         THROW_IF_ERROR( NewIconSuite(&icons) );
  1573.                     PtrToHand(ptr, &icon, size);
  1574.                     THROW_IF_ERROR( AddIconToSuite(icon, icons, kIconType[i]) );
  1575.                 }
  1576.             }
  1577.         CATCH_ALL
  1578.         ENDTRY
  1579.         CloseResFile();
  1580.     }
  1581.     return icons;
  1582. }
  1583.  
  1584. //------------------------------------------------------------------------------
  1585. // PlatformFile::SetCustomIconFamily
  1586. //------------------------------------------------------------------------------
  1587.  
  1588. void
  1589. PlatformFile::SetCustomIconFamily(ODIconFamily icons)
  1590. {
  1591.     // set with kODNULL as the icons to delete the custom icons
  1592.     TRY
  1593.         if (!icons)
  1594.         {
  1595.             // check to see if there's a resFile so that we don't
  1596.             // create one while trying to delete nonexistant icons
  1597.             SetPermission(fsRdPerm);
  1598.             OpenResFile();        // THROW if no resFile
  1599.             CloseResFile();
  1600.         }
  1601.         // write icons to the file
  1602.         SetPermission(fsRdWrPerm);
  1603.         OpenResFile();
  1604.         for( long i=5; i>=0; i-- )
  1605.         {
  1606.             Handle    icon;
  1607.             char    state;
  1608.             
  1609.             if( icons )
  1610.                 THROW_IF_ERROR( GetIconFromSuite(&icon, icons, kIconType[i]) );
  1611.             else
  1612.                 icon = kODNULL;
  1613.             if (icon)
  1614.             {
  1615.                 state = HGetState(icon);
  1616.                 HLock(icon);
  1617.                 WASSERT(GetHandleSize(icon) == kIconSize[i]);
  1618.                 WriteResourcePtr(kIconType[i], kCustomIconResource, *icon, kIconSize[i]);
  1619.                 HSetState(icon, state);
  1620.             } else
  1621.                 DeleteResource(kIconType[i], kCustomIconResource);
  1622.         }
  1623.         CloseResFile();
  1624.     CATCH_ALL
  1625.     ENDTRY
  1626.     SetCustomIcon(icons != kODNULL);
  1627. }
  1628.